﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MTGenome.Gatherer;
using MTGenome.MTG;

namespace MTGenome.UnitTest
{
    [TestClass]
    public class LibraryUnitTest
    {
        private const int DECK_COUNT = 60,
            RAND_MAX = 1000;
        private Random _rand = new Random(Environment.TickCount);
        private List<ICard> _cards = null;
        private ILibrary _library = null;

        /// <summary>
        /// Re-loads our library before each test is run
        /// </summary>
        [TestInitialize]
        public void Initialize()
        {
            //First let's pull 60 random cards and stuff them in the library
            using (IDatabase db = new Database(new DatabaseConnection()))
            {
                int random = _rand.Next(0, RAND_MAX - DECK_COUNT);

                _cards = db.Cards.Skip(random).Take(DECK_COUNT).ToList();
            }

            //Setup the library and load it
            _library = new Library();
            _library.Load(_cards);

            //Do some assertions
            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == DECK_COUNT);
        }

        [TestMethod]
        public void Shuffle()
        {
            //Shuffle 100 times
            for (int i = 0; i < 100; i++)
            {
                _library.Shuffle();
            }

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == DECK_COUNT);
        }

        [TestMethod]
        public void Draw()
        {
            //Draw the whole deck
            for (int i = 0; i < DECK_COUNT; i++)
            {
                var card = _library.Draw();

                Assert.IsNotNull(card);
                Assert.IsNotNull(card.MultiverseID);
                Assert.IsNotNull(card.Name);
                Assert.IsTrue(card == _cards[i]);
            }

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == 0);
        }

        [TestMethod]
        public void ViewTop()
        {
            //Draw the whole deck, while viewing
            for (int i = 0; i < DECK_COUNT; i++)
            {
                var viewed = _library.ViewTop();
                var card = _library.Draw();

                Assert.AreEqual(viewed, card);
                Assert.IsNotNull(card);
                Assert.IsNotNull(card.MultiverseID);
                Assert.IsNotNull(card.Name);
                Assert.IsTrue(card == _cards[i]);
            }

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == 0);
        }

        [TestMethod]
        public void ViewTopX()
        {
            var views = _library.ViewTopX(DECK_COUNT).ToList();
            var cards = _library.DrawX(DECK_COUNT).ToList();

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == 0);
            Assert.IsTrue(views.Count == DECK_COUNT);
            Assert.IsTrue(cards.Count == DECK_COUNT);

            //Draw the whole deck, while viewing
            for (int i = 0; i < DECK_COUNT; i++)
            {
                var viewed = views[i];
                var card = cards[i];

                Assert.AreEqual(viewed, card);
                Assert.IsNotNull(card);
                Assert.IsNotNull(card.MultiverseID);
                Assert.IsNotNull(card.Name);
                Assert.IsTrue(card == _cards[i]);
            }
        }

        [TestMethod]
        public void DrawFromBottom()
        {
            //Draw the whole deck
            for (int i = 0; i < DECK_COUNT; i++)
            {
                var card = _library.DrawFromBottom();

                Assert.IsNotNull(card);
                Assert.IsNotNull(card.MultiverseID);
                Assert.IsNotNull(card.Name);
                Assert.IsTrue(card == _cards[_cards.Count - 1 - i]);
            }

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == 0);
        }

        [TestMethod]
        public void ViewBottom()
        {
            //Draw the whole deck
            for (int i = 0; i < DECK_COUNT; i++)
            {
                var viewed = _library.ViewBottom();
                var card = _library.DrawFromBottom();

                Assert.AreEqual(viewed, card);
                Assert.IsNotNull(card);
                Assert.IsNotNull(card.MultiverseID);
                Assert.IsNotNull(card.Name);
                Assert.IsTrue(card == _cards[_cards.Count - 1 - i]);
            }

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == 0);
        }

        [TestMethod]
        public void ViewBottomX()
        {
            var views = _library.ViewBottomX(DECK_COUNT).ToList();
            var cards = _library.DrawXFromBotton(DECK_COUNT).ToList();

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == 0);
            Assert.IsTrue(views.Count == DECK_COUNT);
            Assert.IsTrue(cards.Count == DECK_COUNT);

            //Draw the whole deck, while viewing
            for (int i = 0; i < DECK_COUNT; i++)
            {
                var viewed = views[i];
                var card = cards[i];

                Assert.AreEqual(viewed, card);
                Assert.IsNotNull(card);
                Assert.IsNotNull(card.MultiverseID);
                Assert.IsNotNull(card.Name);
                Assert.IsTrue(card == _cards[_cards.Count - 1 - i]);
            }
        }

        [TestMethod]
        public void DrawX()
        {
            //Draw the whole deck
            int i = 0;
            foreach (var card in _library.DrawX(DECK_COUNT))
            {
                Assert.IsNotNull(card);
                Assert.IsNotNull(card.MultiverseID);
                Assert.IsNotNull(card.Name);
                Assert.IsTrue(card == _cards[i++]);
            }

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == 0);
        }

        [TestMethod]
        public void DrawXFromBottom()
        {
            //Draw the whole deck
            int i = 0;
            foreach (var card in _library.DrawXFromBotton(DECK_COUNT))
            {
                Assert.IsNotNull(card);
                Assert.IsNotNull(card.MultiverseID);
                Assert.IsNotNull(card.Name);
                Assert.IsTrue(card == _cards[_cards.Count - 1 - i++]);
            }

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == 0);
        }

        [TestMethod]
        public void ViewAll()
        {
            int i = 0;
            foreach (var card in _library.ViewAll())
            {
                Assert.IsNotNull(card);
                Assert.IsNotNull(card.MultiverseID);
                Assert.IsNotNull(card.Name);
                Assert.IsTrue(card == _cards[i++]);
            }
        }

        [TestMethod]
        public void PlaceOnTop()
        {
            //Place the whole deck on top of itself
            foreach (var card in _cards)
            {
                _library.PlaceOnTop(card);

                var top = _library.ViewTop();
                Assert.AreEqual(card, top);
            }

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == DECK_COUNT * 2);
        }

        [TestMethod]
        public void PlaceOnBottom()
        {
            //Place the whole deck on bottom of itself
            foreach (var card in _cards)
            {
                _library.PlaceOnBotton(card);

                var bottom = _library.ViewBottom();
                Assert.AreEqual(card, bottom);
            }

            Assert.IsNotNull(_library);
            Assert.IsTrue(_library.CardCount == DECK_COUNT * 2);
        }
    }
}
